// This class is for the lower-right quadrant of the app.  It is where the labeled boxes get drawn to.
// It essentially acts as the MODEL in this application (keeps a list of observers and notifies them
//  of appropriate changes).

package labeledbox;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;

/*
 * Notes: BVZ provided this file, with basically nothing in it, except for the empty class definition
 *        (i.e., it included the fact that DrawPanel extends CanvasShape).
 *        Note that Kristy's hints state nothing about DrawPanel, and instead only speak about its base class
 *        (CanvasShape). I think BVZ added DrawPanel for this year's assignment. I think its probably b/c he
 *        also uses a CanvasShape as the color swatch in the LabeledBoxControls panel, and therefore the mouse
 *        clicks should be handled differently there compared to in the main drawing panel (lower right panel).
 *
 *        This parent-child situation creates some confusing issues, as to where certain class variables should
 *        exist (i.e., should they exist in CanvasShape, or in DrawPanel?).  Many of the class vars that
 *        DrawPanel use are only contained in CanvasShape. The reason for this is that I first implemented
 *        CanvasShape by following directions in the lab writeup. In retrospect, it may make more sense
 *        to have had many of those class vars actually in this class instead.
 */

public class DrawPanel extends CanvasShape { // CanvasShape extends JPanel


  private LabeledBox selectedLabeledBox = null;
  // Observers list
  private List<ControlPanel_Observer_Interface> observers = new LinkedList<ControlPanel_Observer_Interface>();

  // Constructor
  public DrawPanel() {

    addMouseListener(new MouseAdapter() {
      @Override
      public void mouseClicked(MouseEvent evt) {
        mouseClickedHandler(evt);
      }
    });

  } //// end constructor ////

  // addObserver()
  public void addObserver(ControlPanel_Observer_Interface controlPanel) {

    this.observers.add(controlPanel);
  } ///// end addObserver() ///////



  // Analyze a mouse click:
  //   If it was clicked over an existing LabeledBox, do the follow 4 things:
  //    (a)Select the box  (b) Deselect any previously selected boxes
  //    (c)Change visual properties of the selected and the deslected boxes (d) notify interested control panels
  // NOTE: BVZ's example executable, as well as my code both do not effectively discern the topmost box
  //       of overlapping (stacked) boxes when a click is considered over 2 or more overlapping boxes.
  //       This results in a lower-z-order box sometimes getting selected instead of the top-most box.
  //       I could later add code to properly select only the top-most box in this scenario.
  private void mouseClickedHandler(MouseEvent evt) {

    // Testing code
    System.out.println("You clicked at " + evt.getX() + "," + evt.getY());

    System.out.println("Iterating through Shapes to determine if mouse click was over one...");
    for (Shape shape : shapes) {
      System.out.println("Object at " + shape.getLeft() + "," + shape.getTop() + " ..." );
      if(shape.contains(evt.getX(), evt.getY())) System.out.println("   ... CONTAINS the click!");
      else  System.out.println("   ... does not contain the click");
    }
    // end testing code


    // "Deselect" the previously selected item by changing its visual properties back to the defaults.
    if(selectedLabeledBox != null)
      changePropsToDeselected(selectedLabeledBox);

    // First mark that no box is selected. Then we'll check if any actually are selected.
    selectedLabeledBox = null;

    // find the first LabeledBox in the vector that contains the point and mark it as the selected labeled box
    for (Shape shape : shapes) {
  
      if(shape.contains(evt.getX(), evt.getY()))  {
        // Mark this shape as the selected item
        selectedLabeledBox = (LabeledBox) shape;
        // "Select" the selected item by changing the it's visual properties
        changePropsToSelected((LabeledBox)shape);
        break;
      }
    }
    // NOTIFY the interested control panels of the selected LabeledBox state
    // (if no box is selected, null will be passed, and the observers can act accordingly)
    for (ControlPanel_Observer_Interface observer : observers) {
      observer.notifyBoxSelected(selectedLabeledBox);
    }

    repaint();

  } ///// end mouseClickedHandler() ///////////


  // Change the visual properties of the given labeled box to that of a "deselected" item
  private void changePropsToDeselected(LabeledBox labBox) {

    // Reset the text color
    labBox.label.setLineColor(LabeledBox.DEFAULT_TEXT_COLOR);
    // Reset the box fill color
    labBox.setFilled(true);
    // Reset the outer box border color
    labBox.setLineColor(LabeledBox.DEFAULT_BOX_BORDER_COLOR);
  } ///// end changePropsToDeselected() /////////////


  // Change the visual properties of the given labeled box to that of a "selected" item
  private void changePropsToSelected(LabeledBox labBox) {
    
    // Set the text color
    labBox.setTextColor(LabeledBox.DEF_SELECTED_TEXT_COLOR);
    // Set the fill boolean
    labBox.setFilled(LabeledBox.DEF_SELECTED_BOX_FILL_BOOL);
    // Set the outer box border color
    labBox.setLineColor(LabeledBox.DEF_SELECTED_BOX_BORDER_COLOR);
  } ///// end changePropsToSelected() /////////////
  
  
  
  public Dimension getPreferredSize() {
    return new Dimension(600,500);
  }


} //////////////////////// end class DrawPanel /////////////////////////
	
 
